#coding=utf-8
import os
import shutil
import tkinter as tk
from tkinter import *
import time
updatafile_path_list = []   #所有更新文件的路径

class App():
    def __init__(self, root):
        self.root = root
        self.root.columnconfigure(1, weight=1)
        self.root.rowconfigure(3, weight=1)
        frame = tk.Frame(root)
        frame.grid(sticky= "nsew")
        self.CreateFrame()

    def CreateFrame(self):
        self.updatepath_label_0 = Label(self.root,text="更新文件路径:",width = 13,)
        self.updatepath_label_0.grid(row = 0 ,column = 0 ,padx = 12 ,pady = 6, sticky = W )
        self.updatapath = StringVar()
        self.updatepath_e_0 = Entry(self.root,textvariable=self.updatapath)
        self.updatepath_e_0.grid(row = 0 , column = 1,pady = 6,sticky= "nsew")
        self.getpath_button = Button(self.root,text="生成路径",command=self.GetPath,width = 10)
        self.getpath_button.grid(row=0,column=2, pady = 6,padx = 12 )

        self.bakpath_label_0 = Label(self.root, text="备份文件路径:",width = 13,)
        self.bakpath_label_0.grid(row=1, column=0, padx=12, pady=6, sticky = W )
        self.bakpath = StringVar()
        self.bakpath_e_1 = Entry(self.root,textvariable=self.bakpath)
        self.bakpath_e_1.grid(row=1, column=1, pady=2,sticky= "nsew")
        # self.bak_button = Button(self.root,text="备份",width = 10,command=self.Bak_file)
        # self.bak_button.grid(row = 1 , column = 2 ,padx = 12, pady = 6)

        self.datepath_label_0 = Label(self.root, text="文件路径:",width = 13,)
        self.datepath_label_0.grid(row=2, column=0, padx=12, pady=6, sticky = W )
        self.datapath = StringVar()
        self.datepath_e_2 = Entry(self.root,textvariable=self.datapath)
        self.datepath_e_2.grid(row=2, column=1,  pady=6,sticky= "nsew")
        self.updatabutton = Button(self.root,text="备份更新",width = 10 ,command=self.Updata_file)
        self.updatabutton.grid(row = 2 , column = 2 ,pady = 6,padx = 12)


        #用于显示信息的文本框
        self.text = Text(self.root,height=10)
        self.text.grid(row = 3,column = 0,columnspan=3,padx=0, pady=12,sticky= "news")
        #侧边栏滑动滚轮
        self.sb = Scrollbar(self.root)
        self.sb.grid(row =3 ,column = 3,sticky = "news")
        self.text['yscrollcommand'] = self.sb.set
        self.sb['command'] = self.text.yview

        #增加版本回滚的按钮功能
        self.version_rollback = Button(self.root,text="版本回滚",fg='red',command=self.Version_Rollback)
        self.version_rollback.grid(row = 4,pady = 1,padx = 1)


    #获取备份，项目路径的方法
    def GetPath(self):
        updatapath = self.updatepath_e_0.get()
        if not updatapath[-1] == "\\":
            updatapath = updatapath + "\\"
        path_value = updatapath.split("\\")
        self.updatapath.set(updatapath)
        self.bakpath.set(updatapath.replace("Web_update", 'Web_bak').replace("Web_Update", 'Web_bak').replace("web_update","web_bak").replace("ClientApp_update","ClientApp_bak").replace("ClientApp_Update","ClientApp_bak").replace("clientApp_update","clientApp_bak"))
        self.datapath.set(path_value[0] + "\\" + path_value[1].replace("Web_update", 'Web').replace("web_update","web").replace("Web_Update", 'Web').replace("ClientApp_update","ClientApp").replace("ClientApp_Update","ClientApp").replace("clientApp_update","clientApp") + "\\" + path_value[2] + "\\")
        self.text.delete(1.0,END)
    #备份更新的方法
    def Updata_file(self):
        self.text.insert(1.0,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ": 开始进行备份..." + "\n")
        updata_path = self.updatepath_e_0.get()
        bak_path = self.bakpath_e_1.get()
        web_path = self.datepath_e_2.get()
        i = 0
        n = 0
        for dir_path, subdirs, files in os.walk(updata_path):
            bak_dir_path = dir_path.replace(updata_path,bak_path)  # 备份文件夹的目录
            data_dir_path = dir_path.replace(updata_path, web_path)  # 线上站点的目录
            try:
                os.makedirs(bak_dir_path)  # 创建备份文件夹的目录
            except WindowsError:
                # 将错误信息显示到文本框
                self.text.insert(1.0,"备份文件夹已存在，无法重复创建，文件夹路径：" + bak_dir_path + "\n")
            try:
                if os.path.exists(data_dir_path) == False:  # 更新文件是否存在新目录，存在则创建
                    os.makedirs(data_dir_path)
            except WindowsError:
                # 将错误信息显示到文本框
                self.text.insert(1.0,"项目文件中已存在新增文件，无法重复创建，新增文件夹路径：" + data_dir_path + "\n")
            # 获取所有更新文件的路径
            for filepath in files:
                updata_filepath = os.path.join(dir_path, filepath)
                updatafile_path_list.append(updata_filepath)
                # 判断更新文件在线上项目中是否存在，如果存在则复制到备份目录
                data_filepath = updata_filepath.replace(updata_path, web_path)
                bak_filepath = updata_filepath.replace(updata_path, bak_path)
                if os.path.exists(data_filepath) == True:
                    try:
                        shutil.copy2(data_filepath, bak_filepath)
                        i = i + 1
                    except Exception as e:
                        self.text.insert(1.0, "备份发生一个异常:\n" + str(e) + "\n")
                else:
                    n = n + 1
                    self.text.insert(1.0, time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ": " + "NewFile：" + updata_filepath + "\n")
        #将备份的信息显示到文本框
        self.text.insert(1.0, time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ": " + (str(n)) + "个新文件" + "\n")
        self.text.insert(1.0, time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ": " + (str(i)) + "个文件已备份..." + "\n")

        self.text.insert(1.0,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ": 开始进行更新..."  + "\n")
        m = 0
        #遍历所有更新文件，根据规则生成项目文件的路径，进行复制替换
        for updatafile_path in updatafile_path_list:
            datafile_path = updatafile_path.replace(updata_path, web_path)
            try:
                shutil.copy2(updatafile_path, datafile_path)
                m = m + 1
            except Exception as e:
                self.text.insert(1.0, "更新发生一个异常:\n" + str(e) + "\n")
        #将更新的信息显示到文本框
        self.text.insert(1.0,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ": " + (str(m) + "个文件已更新..." + "\n"))
        del updatafile_path_list[:]

    def Version_Rollback(self):
        self.text.insert(1.0,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())) + ": 开始进行还原..." + "\n")
        updata_path = self.updatepath_e_0.get()
        bak_path = self.bakpath_e_1.get()
        web_path = self.datepath_e_2.get()
        for dir_path, subdirs, files in os.walk(updata_path):
            # 获取所有更新文件的路径
            for filepath in files:
                updata_filepath = os.path.join(dir_path, filepath)
                data_filepath = updata_filepath.replace(updata_path, web_path)   #已更新的线上文件路径
                #删除线上环境中已更新的文件
                try:
                    os.remove(data_filepath)
                except Exception as e:
                    self.text.insert(1.0, "删除更新文件时发生一个异常:\n" + str(e) + "\n")
        i = 0
        for dir_path, subdirs, files in os.walk(bak_path):
            for filepath in files:
                bak_filepath = os.path.join(dir_path,filepath)
                data_filepath = bak_filepath.replace(bak_path,web_path)
                #将备份文件复制替换到线上环境中
                try:
                    shutil.copy2(bak_filepath,data_filepath)
                    i = i + 1
                except Exception as e:
                    self.text.insert(1.0, "还原备份时发生一个异常:\n" + str(e) + "\n")

        self.text.insert(1.0, time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())) + ": " + (str(i) + "个文件已还原..." + "\n"))


root = tk.Tk()
root.title("UpdateTool_V1.3")
app = App(root)
root.mainloop()

#V1.1
#修改界面输入框为自适应屏幕
#增加备份更新时显示当前时间
#V1.2
#修复挂机程序路径无法生成的问题，优化线上项目路径的生成方式
#V1.3
#加入滑动侧边栏
#加入版本回滚功能
#信息显示倒序排列
#挂机路径生成问题
#备份更新用一个键
#解决路径生成多次点击会生成多个斜杠问题
